//
//  Reaction+Extension.swift
//  SwiftProject
//
//  Created by qindong on 2021/3/17.
//

import Foundation

//MARK: - UIButton Reactive 扩展
extension Reactive where Base: UIButton {
    // MARK: - 扩展按钮可用观察者
    var buttonIsEnable: Binder<Bool> {
        return Binder(base) { (button, result) in
            button.isEnabled = result
            if result {
                button.alpha = 1.0
            } else {
                button.alpha = 0.6
            }
        }
    }
}

class RxImagePickerDelegateProxy: RxNavigationControllerDelegateProxy, UIImagePickerControllerDelegate {
    public init(imagePicker: UIImagePickerController) {
        super.init(navigationController: imagePicker)
    }
}

//MARK: - UIImagePickerController Reactive 扩展
extension Reactive where Base: UIImagePickerController {
    static func dismissViewController(viewController: UIViewController, animated: Bool) {
        /// 是否有控制器在进程中没有显示或消失
        if viewController.isBeingPresented || viewController.isBeingDismissed {
            DispatchQueue.main.async {// 异步递归调用
                dismissViewController(viewController: viewController, animated: animated)
            }
        } else if viewController.presentingViewController != nil {
            viewController.dismiss(animated: animated, completion: nil)
        }
    }
    
    private func castOrThrow<T>(resultType: T.Type, object: Any) throws -> T {
        guard let resultValue = object as? T else {
            throw RxCocoaError.castingError(object: object, targetType: resultType)
        }
        
        return resultValue
    }
    
    public var didCancel: Observable<()> {
        return delegate.methodInvoked(#selector(UIImagePickerControllerDelegate.imagePickerControllerDidCancel(_:))).map { (_) -> () in }
    }
    
    public var didFinishPickingMediaWithInfo: Observable<[UIImagePickerController.InfoKey: AnyObject]> {
        return delegate.methodInvoked(#selector(UIImagePickerControllerDelegate.imagePickerController(_:didFinishPickingMediaWithInfo:))).map { (a) in
            return try castOrThrow(resultType: Dictionary<UIImagePickerController.InfoKey, AnyObject>.self, object: a[1])
        }
    }
    
    static func createWithParent(_ parent: UIViewController?, animated: Bool = true, configureImagePicker: @escaping (UIImagePickerController) throws -> () = { x in }) -> Observable<UIImagePickerController> {
        return Observable.create { [weak parent] observer in
            let imagePicker = UIImagePickerController()
            let dismissDisposable = imagePicker.rx.didCancel.subscribe(onNext: { [weak imagePicker] in
                guard let imagePicker = imagePicker else {
                    return
                }
                dismissViewController(viewController: imagePicker, animated: animated)
            })
            do {
                try configureImagePicker(imagePicker)
            }
            catch let error {
                observer.on(.error(error))
                return Disposables.create()
            }

            guard let parent = parent else {
                observer.on(.completed)
                return Disposables.create()
            }
            imagePicker.modalPresentationStyle = .fullScreen
            parent.present(imagePicker, animated: animated, completion: nil)
            observer.on(.next(imagePicker))

            return Disposables.create(dismissDisposable, Disposables.create {
                dismissViewController(viewController : imagePicker, animated: animated)
            })
        }
    }
}

//MARK: - UIAlertController Reactive 扩展
extension UIAlertController {
    struct AlertAction {
        var title: String?
        var style: UIAlertAction.Style

        static func action(title: String?, style: UIAlertAction.Style = .default) -> AlertAction {
            return AlertAction(title: title, style: style)
        }
    }
 
    static func present(
        in viewController: UIViewController,
        title: String?,
        message: String?,
        style: UIAlertController.Style,
        actions: [AlertAction])
        -> Observable<Int>
    {
        return Observable.create { observer in
            let alertController = UIAlertController(title: title, message: message, preferredStyle: style)

            actions.enumerated().forEach { index, action in
                let action = UIAlertAction(title: action.title, style: action.style) { _ in
                    observer.onNext(index)
                    observer.onCompleted()
                }
                alertController.addAction(action)
            }

            viewController.present(alertController, animated: true, completion: nil)
            return Disposables.create { alertController.dismiss(animated: true, completion: nil) }
        }
    }
}

extension QMUIAlertController {
    struct AlertAction {
        var title: String?
        var style: QMUIAlertActionStyle

        static func action(title: String?, style: QMUIAlertActionStyle = .default) -> AlertAction {
            return AlertAction(title: title, style: style)
        }
    }

    static func present(
        title: String?,
        message: String?,
        style: QMUIAlertControllerStyle,
        actions: [AlertAction])
        -> Observable<Int>
    {
        return Observable.create { observer in
            let alertController = QMUIAlertController(title: title, message: message, preferredStyle: style)
            alertController.orderActionsByAddedOrdered = true
            actions.enumerated().forEach { index, action in
                let action = QMUIAlertAction(title: action.title, style: action.style) { _,_  in
                    observer.onNext(index)
                    observer.onCompleted()
                }
                alertController.addAction(action)
            }
            alertController.showWith(animated: true)
            return Disposables.create { alertController.hideWith(animated: true) }
        }
    }
}
